/*!
// Testweb v0.4.0
// http://or-change.cn
// Copyright 2014 OrChange Inc. All rights reserved.
// Licensed under the GPL License.
*/
/*jslint vars: true, forin: true, plusplus: true */
/*global define: false */
/**
 * Process Pool Manager.
 *
 * @module ppm
 * @requires OC
 * @requires Process
 * @example
 *     var ppm = require("./oc.ppm"); //How to require ppm module.
 */
define(function (require, exports, module) {
	'use strict';
	var ppm,
		dim = require("./remote"),
		OC = require("lib/core/oc"),
		Step = require("lib/class/step"),
		EventStep = require("lib/class./eventstep"),
		DelayStep = require("lib/class/delaystep"),
		Process = require("lib/class/process"),
		Condition = require("lib/class/condition"),
		Dictionary = require("lib/class/dictionary");
	/**
	 * ppm
	 * @class ppm
	 */
	window.O = ppm = {
		/**
		 * Storage all process.
		 * @property process_set
		 * @type array
		 */
		process_set: [],
		/**
		 *Point to a single process in process_set.
		 * @property CURRENT
		 * @type Process
		 * @default null
		 */
		CURRENT: null
	};
	/**
	 * Import a program in object array.
	 * @method importByObject
	 * @returns {Process} this
	 * @chainable
	 * @example
	 *		ppm.$importProgram([
	 *			{
	 *				type:"Delay",
	 *				name:"xxx",
	 *				id:"xxx",
	 *				delay:"xxx",
	 *				object:"xxx",
	 *				action:"xxx",
	 *				param:"xxx"
	 *			},
	 *			...
	 *		]);
	 */
	ppm.$importProgram = function (program) {
		var step, i, len;
		len = program.length;
		for (i = 0; i < len; i += 1) {
			step = program[i];
			switch (step.type) {
			case "Delay":
				this.CURRENT.addStep(new DelayStep(step));
				break;
			case "Event":
				step.condition = new Condition(step.condition);
				this.CURRENT.addStep(new EventStep(step));
				break;
			default:
				this.CURRENT.addStep(new DelayStep(step));
				break;
			}
		}
		return this;
	};
	ppm.$importDictionary = function (dictionary) {
		this.CURRENT.addDictionary(new Dictionary(dictionary));

		return this;
	};
	/**
	 * 创建一个空白的Process对象，并将current指针指向这个新过程
	 * @method createProcess
	 * @param options
	 * @options like constructor Process.
	 * @returns this.CURRENT.
	 */
	ppm.createProcess = function (options) {
		var index;
		index = this.process_set.push(new Process(options)) - 1;
		this.CURRENT = this.process_set[index];

		return this.CURRENT;
	};
	ppm.modifyProcess = function (options) {
		var key, process = this.CURRENT;

		options.MAX_LOOPS = parseInt(options.MAX_LOOPS, 0);
		for (key in options) {
			process.setProperty(key, options[key]);
			process.setInfo(key, options[key]);
		}

		return this.CURRENT;
	};
	/**
	 * open a new process
	 * @method openProcess
	 * @param obj
	 * @return CURRENT
	 */
	ppm.openProcess = function (obj) {
		var that = this;
		ppm.createProcess({
			MAX_LOOPS: obj.MAX_LOOPS,
			name: obj.name,
			origin: obj.origin,
			comment: obj.comment
		});
		this.$importProgram(obj.program);

		dim.query("getDictionary", obj.dictionary, function (dictionary) {
			that.$importDictionary(dictionary);
		});

		return this.CURRENT;
	};
	/**
	 * return the deleted process's name
	 * @method destroyProcess
	 * @param pid
	 * @return process
	 */
	ppm.destroyProcess = function (pid) {
		var process;

		process = this.process_set[pid - 1];
		this.process_set.splice(pid, 1);

		return process;
	};
	/**
	 * Playing current process
	 * @method playProcess
	 * @returns {object} CURRENT
	 */
	ppm.playProcess = function () {
		ppm.CURRENT.play();

		return this.CURRENT;
	};
	/**
	 * Resume current process
	 * @method resumeProcess
	 * @returns {object} CURRENT
	 */
	ppm.resumeProcess = function () {
		ppm.CURRENT.resume();

		return this.CURRENT;
	};
	/**
	 * Pausing current process
	 * @method Pause
	 * @returns {object} CURRENTprocess
	 */
	ppm.pauseProcess = function () {
		ppm.CURRENT.pause();

		return this.CURRENT;
	};
	/**
	 * Stopping current process
	 * @method stopProcess
	 */
	ppm.stopProcess = function () {
		ppm.CURRENT.stop();

		return this.CURRENT;
	};
	/**
	 * Checkout  the process of the specified pid
	 * @method checkout
	 * @param pid
	 * @returns {string} process.name
	 */
	ppm.checkout = function (pid) {
		ppm.CURRENT = ppm.process_set[pid];
		return ppm.CURRENT.name;
	};
	/**
	 * Playing the next step
	 * @method nextStep
	 * @returns CURRENT
	 */
	ppm.nextStep = function () {
		ppm.CURRENT.goOn();

		return this.CURRENT;
	};
	/**
	 * Appending a new step
	 * @method appendToStep
	 * @param index
	 * @param step
	 * @returns  CURRENT
	 */
	ppm.appendToStep = function (step, index) {
		if (index === undefined) {
			ppm.CURRENT.addStep(step);
		} else {
			ppm.CURRENT.insertStep(index, step);
		}

		return this.CURRENT;
	};
	/**
	 * Removing a specified step
	 * @method removeStep
	 * @param index
	 * @returns process
	 */
	ppm.removeStep = function (index) {
		return this.CURRENT.deleteStep(index);
	};
	ppm.replaceStep = function (index, step) {
		return this.CURRENT.replaceStep(index, step.setParent(this.CURRENT));
	};
	ppm.moveStepUp = function (index) {
		return this.CURRENT.moveStepUp(index);
	};
	ppm.moveStepDown = function (index) {
		return this.CURRENT.moveStepDown(index);
	};

	/**
	 * Exporting the list of process
	 * @method getProcessList
	 * @returns {objec} process
	 */
	ppm.getProcessList = function (data_key_name) {
		var i, name, len, data = {},
			process_list = [];
		data_key_name = data_key_name || "local";

		len = this.process_set.length;
		for (i = 0; i < len; i += 1) {
			name = this.process_set[i].getInfo("name");
			process_list.push({
				process_name: name
			});
		}
		data[data_key_name] = process_list;
		return data;
	};
	ppm.getProcessSerialization = function (process_index) {
		var process, data;
		if (process_index === undefined) {
			process = this.CURRENT;
		} else {
			process = this.process_set[process_index];
		}

		data = {
			name: process.getInfo("name"),
			comment: process.getInfo("comment"),
			MAX_LOOPS: process.getProperty("MAX_LOOPS"),
			origin: process.getProperty("origin")
		};
		//TODO
		data.ata_dict = "dictionary";

		return data;
	};
	/**
	 * Exporting the list of step
	 * @method getProgramList
	 * @returns {objec} program
	 */
	ppm.getProgramList = function () {
		var i, name, len,
			data = {
				program: []
			};
		len = this.CURRENT.program.length;
		for (i = 0; i < len; i += 1) {
			name = this.CURRENT.program[i].getInfo("name");
			data.program.push({
				step_name: name
			});
		}
		return data;
	};
	ppm.getStepSerialization = function (index) {
		var step, step_type, data, param;

		step = this.CURRENT.getStep(index);
		step_type = step instanceof DelayStep ? "Delay" : "Event";

		data = {
			name: step.getInfo("name"),
			author: step.getInfo("author"),
			updatetime: step.getInfo("updatetime"),
			comment: step.getInfo("comment"),

			type: step_type,
			object: step.getProperty("object"),
			action: step.getProperty("action")
		};

		if (step_type === "Delay") {
			data.delay = step.getProperty("delay");
		} else {
			data.condition = step.getProperty("condition").toString();
		}

		param = step.getProperty("param");
		if (step.action === "val") {
			data.param_type = param.type;
			data.param_value = param.value;
		} else if (step.action === "scroll") {
			data.position_top = param.position_top;
			data.position_left = param.position_left;
		}

		return data;
	};
	/**
	 * Return if this current process has a Dictionary. This method just use to check
	 * the process in CURRENT.
	 *
	 * return {boolean} 检查结果
	 */
	ppm.hasDictionary = function () {
		if (this.CURRENT.data_dict instanceof Dictionary) {
			return true;
		}
		return false;
	};
	ppm.getDictionaryKeys = function () {
		return this.CURRENT.data_dict.getKeys();
	};

	// 过程编辑
	exports.create = function (options) {
		return ppm.createProcess(options);
	};
	exports.destroy = function (pid) {
		return ppm.destroyProcess(pid);
	};
	exports.modify = function (options) {
		return ppm.modifyProcess(options);
	};
	exports.open = function (process_json) {
		return ppm.openProcess(process_json);
	};
	exports.checkout = function (process_index) {
		return ppm.checkout(process_index);
	};

	// 播放器控制
	exports.play = function () {
		return ppm.playProcess();
	};
	exports.resume = function () {
		return ppm.resumeProcess();
	};
	exports.pause = function () {
		return ppm.pauseProcess();
	};
	exports.stop = function () {
		return ppm.stopProcess();
	};
	exports.next = function () {
		return ppm.nextStep();
	};

	// 步骤编辑
	exports.appendTo = function (step, index) {
		return ppm.appendToStep(step, index);
	};
	exports.removeStep = function (index) {
		return ppm.removeStep(index);
	};
	exports.insertStep = function (index) {
		//TODO
	};
	exports.replaceStep = function (index, step) {
		return ppm.replaceStep(index, step);
	};
	exports.moveStepUp = function (index) {
		return ppm.moveStepUp(index);
	};
	exports.moveStepDown = function (index) {
		return ppm.moveStepDown(index);
	};

	// 数据输出
	exports.getProcessList = function (data_key_name) {
		return ppm.getProcessList(data_key_name);
	};
	exports.getProcessInfo = function (process_index) {
		return ppm.getProcessInfo(process_index);
	};
	exports.getProgramList = function () {
		return ppm.getProgramList();
	};
	exports.getStepSerialization = function (step_index) {
		return ppm.getStepSerialization(step_index);
	};
	exports.getProcessSerialization = function (process_index) {
		return ppm.getProcessSerialization(process_index);
	};
	exports.hasDictionary = function () {
		return ppm.hasDictionary();
	};
	exports.getDictionaryKeys = function () {
		return ppm.getDictionaryKeys();
	};
});